import traci

from scene.constants import EMERGENCY_LANE_ALLOWED_VEHICLE_TYPE, ON, OFF, DEL, SPECIAL_LANE_ALLOWED_VEHICLE_TYPE


class SpecialLaneDomain:

    def __init__(self):
        self.special_lane_polygon = {}

    def set_special_lane_polygon(self,  edge: str, lane_index: int, pos: list, switch=ON):
        """"
        新增应急车道区域 (str, int, double, list((double, double)), integer) -> None
        :param edge: 边缘
        :param lane_index: 道路序号
        :param pos: 区域坐标集合
        :param switch: 开关
        :return:
        """
        polygon_id = edge + '_' + str(lane_index)
        special_lane_item = SpecialLaneItem(polygon_id, edge, lane_index, pos, switch)
        self.special_lane_polygon[polygon_id] = special_lane_item
        traci.lane.setAllowed(polygon_id, SPECIAL_LANE_ALLOWED_VEHICLE_TYPE)

        # traci.edge.subscribeContext(edge, tc.CMD_GET_VEHICLE_VARIABLE, 20, [tc.VAR_LANE_INDEX, tc.VAR_TYPE])

    def get_special_lane_polygon(self, polygon_id: str):
        """
        获取指定应急车道区域 (str) -> AccidentItem
        :param polygon_id: 应急车道区域id
        :return: AccidentItem
        """
        return self.special_lane_polygon.get(polygon_id)

    def get_special_lane_polygon_list(self):
        """
        获取所有应急车道区域
        :return: list(dict)
        """
        if len(self.special_lane_polygon) < 1:
            return []
        return list(map(lambda item: item[1].to_dict(), self.special_lane_polygon.items()))

    def control_special_lane(self, polygon_id: str, switch: int):
        """
        控制应急车道区域 （str, int） -> int
        :param
        polygon_id: 区域id
        :param switch: -1：删除 0：关闭 1：开启
        :return: 0: 失败 1：成功
        """
        assert polygon_id in self.special_lane_polygon, '应急车道不存在'
        result = 0
        special_lane_item = self.special_lane_polygon[polygon_id]
        if special_lane_item is not None and special_lane_item.switch != switch:
            if switch == ON:
                self.special_lane_polygon[polygon_id].switch = ON
                traci.lane.setAllowed(polygon_id, SPECIAL_LANE_ALLOWED_VEHICLE_TYPE)
            elif switch == OFF:
                self.special_lane_polygon[polygon_id].switch = OFF
                traci.lane.setDisallowed(polygon_id, [])
            elif switch == DEL:
                del self.special_lane_polygon[polygon_id]
                traci.lane.setDisallowed(polygon_id, [])
            result = 1
        return result



class SpecialLaneItem:

    def __new__(cls, *args, **kwargs):
        return super().__new__(cls)

    def __init__(self, polygon_id, edge, lane_index, pos, switch=ON):
        self.polygon_id = polygon_id
        self.edge = edge
        self.lane_index = lane_index
        self.pos = pos
        self.switch = switch

    def to_dict(self):
        return {
            'polygonId': self.polygon_id,
            'pos': self.pos,
            'edge': self.edge,
            'laneIndex': self.lane_index,
            'switch': self.switch
        }